/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package MessageIO;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.StringTokenizer;

/**
 * MessageReceiver listens for messages from a client and then delivers message
 * to a MessageListener
 * @author VismonteM
 */
public class MessageReceiver implements Runnable
    {
    private BufferedReader input;//Reads the input
    private MessageListener listener;//Listens for input threw the input
    private boolean keepListening;//determines if it keeps listening
    private ArrayList<ChatUsername> userNames;//the list of userNames

    /**
     * Creates a new Message Receiver
     * @param messageListener to where to deliver message
     * @param clientSocket the client to listen to
     */
    public MessageReceiver(MessageListener messageListener, Socket clientSocket
            ,ArrayList<ChatUsername> names)
        {
        super();
        listener = messageListener;
        userNames = names;
        keepListening = true;//ends run when false
        try
            {
            clientSocket.setSoTimeout(5000);//sets timeout
            input = new BufferedReader(new InputStreamReader(
                    clientSocket.getInputStream()));
            //makes a BufferedReader to read incoming messages
            }
        catch (IOException io)
            {
            io.printStackTrace();
            }
        }

    /**
     * Determines if the Username is unused by checking through the username
     * ArrayList
     * @param userName the username to check for in the list
     * @return true if it is unused. false if it is used
     */
    private boolean isUnusedUsername(String userName)
        {
        for (ChatUsername name: userNames)
            if (name.getUserName().equals(userName))
                return false;
        return true;
        }


    /**
     * Listen for new messages and deilver them to MessageListener
     */
    public void run()
        {
        String message = null;//incoming message
        while (keepListening)//listen for messages until told to disconnect
            {
            try
                {
                message = input.readLine();//read message from client
                if (message != null)//makes sure its not null
                    {
                    StringTokenizer token = new StringTokenizer(message,
                            SocketConstants.MESSAGE_SEPERATOR);
                    //retrieves the username and message as two different strings
                    if ( token.countTokens() == 0)//continue if theres no
                        continue;//tokens
                    if (token.countTokens() == 2)//if its just a message being
                        //sent
                        {
                        listener.messageReceived(token.nextToken()//userName
                                , token.nextToken());//message
                        //delievers the message to the receiver
                        }
                    else
                        {
                        String temp = message.substring(3, message.length());
                        if (temp.indexOf(SocketConstants.USERNAME_INDICATOR) != -1)
                            //if a new user is trying to enter
                            {
                            temp = temp.substring(0, temp.length() - SocketConstants.
                                    USERNAME_INDICATOR.length());
                            token = new StringTokenizer(temp, "@");
                            String user = token.nextToken();//seperate the user
                            String ipadd = token.nextToken();//and ip address
                            if (isUnusedUsername(user))//if it is unused
                                {
                                listener.messageReceived("", SocketConstants.
                                        TO_NEW_USER + "@" + user + "$$" +
                                        userNames.toString());
                                /*send it a list of the current users using a
                                 * string */
                                try
                                    {
                                    Thread.sleep(100);//sleep so it has time
                                    }//to send the last message
                                catch (InterruptedException ex)
                                    {
                                    ex.printStackTrace();
                                    }
                                listener.messageReceived("Server", user + " " +
                                        SocketConstants.SERVER_ROOM_ENTER);
                                //Server announces a new User has entered
                                userNames.add(new ChatUsername(user,ipadd));
                                //adds the new user to the ArrayList
                                }
                            else//the username must be used
                                {
                                listener.messageReceived("", SocketConstants.
                                        TERMINATE_USER + temp);
                                /*Sends a string out to terminate the user
                                 * at the specific IP address */
                                }
                            }
                        else//the only other thing would be a disconnect
                            {
                            if (temp.indexOf(SocketConstants.DISCONNECT_STRING)
                                    == -1)
                                return;
                            temp = temp.substring(0, temp.length() - SocketConstants.
                                    DISCONNECT_STRING.length());
                            //finds the user that it needs to terminate
                            token = new StringTokenizer(temp, "@");
                            String user = token.nextToken();
                            String ipadd = token.nextToken();
                            userNames.remove(new ChatUsername(user, ipadd));
                            //removes the user from the ArrayList
                            listener.messageReceived("Server", user + " " +
                                    SocketConstants.SERVER_ROOM_LEFT);
                            //Server says user left the room
                            keepListening = false;//dont listen anymore
                            }
                        }
                    }
                }
            catch (SocketTimeoutException st)
                {
                continue;
                }
            catch (IOException io)
                {
                break;
                }
            }


        try
            {
            input.close();//closes bufferedreader
            }
        catch (IOException io)
            {
            io.printStackTrace();
            }
        }

    }
